home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / gnumake / make360.zoo / function.c < prev    next >
C/C++ Source or Header  |  1991-08-07  |  30KB  |  1,187 lines

  1. /* Variable function expansion for GNU Make.
  2. Copyright (C) 1988, 1989 Free Software Foundation, Inc.
  3. This file is part of GNU Make.
  4.  
  5. GNU Make is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 1, or (at your option)
  8. any later version.
  9.  
  10. GNU Make is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with GNU Make; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include "make.h"
  20. #include "variable.h"
  21. #include "dep.h"
  22. #include "commands.h"
  23. #include "job.h"
  24. #include <errno.h>
  25.  
  26. extern int errno;
  27.  
  28. static char *string_glob ();
  29.  
  30. /* Store into VARIABLE_BUFFER at O the result of scanning TEXT and replacing
  31.    each occurrence of SUBST with REPLACE. TEXT is null-terminated.  SLEN is
  32.    the length of SUBST and RLEN is the length of REPLACE.  If BY_WORD is
  33.    nonzero, substitutions are done only on matches which are complete
  34.    whitespace-delimited words.  If SUFFIX_ONLY is nonzero, substitutions are
  35.    done only at the ends of whitespace-delimited words.  */
  36.    
  37. char *
  38. subst_expand (o, text, subst, replace, slen, rlen, by_word, suffix_only)
  39.      char *o;
  40.      char *text;
  41.      char *subst, *replace;
  42.      unsigned int slen, rlen;
  43.      int by_word, suffix_only;
  44. {
  45.   register char *t = text;
  46.   register char *p;
  47.  
  48.   if (slen == 0 && !by_word && !suffix_only)
  49.     {
  50.       /* The first occurrence of "" in any string is its end.  */
  51.       o = variable_buffer_output (o, t, strlen (t));
  52.       if (rlen > 0)
  53.     o = variable_buffer_output (o, replace, rlen);
  54.       return o;
  55.     }
  56.  
  57.   while ((p = sindex (t, 0, subst, slen)) != 0)
  58.     {
  59.       /* Output everything before this occurrence of the string to replace.  */
  60.       if (p > t)
  61.     o = variable_buffer_output (o, t, p - t);
  62.  
  63.       /* If we're substituting only by fully matched words,
  64.      or only at the ends of words, check that this case qualifies.  */
  65.       if ((by_word
  66.        && ((p > t && p[-1] != ' ' && p[-1] != '\t')
  67.            || (p[slen] != '\0' && p[slen] != ' ' && p[slen] != '\t'))
  68.        || (suffix_only
  69.            && (p[slen] != '\0' && p[slen] != ' ' && p[slen] != '\t'))))
  70.     /* Struck out.  Output the rest of the string that is
  71.        no longer to be replaced.  */
  72.     o = variable_buffer_output (o, subst, slen);
  73.       else if (rlen > 0)
  74.     /* Output the replacement string.  */
  75.     o = variable_buffer_output (o, replace, rlen);
  76.  
  77.       /* Advance T past the string to be replaced.  */
  78.       t = p + slen;
  79.     }
  80.  
  81.   /* Output everything left on the end.  */
  82.   if (*t != '\0')
  83.     o = variable_buffer_output (o, t, strlen (t));
  84.  
  85.   return o;
  86. }
  87.  
  88.  
  89. /* Store into VARIABLE_BUFFER at O the result of scanning TEXT
  90.    and replacing strings matching PATTERN with REPLACE.
  91.    If PATTERN_PERCENT is not nil, PATTERN has already been
  92.    run through find_percent, and PATTERN_PERCENT is the result.
  93.    If REPLACE_PERCENT is not nil, REPLACE has already been
  94.    run through find_percent, and REPLACE_PERCENT is the result.  */
  95.  
  96. char *
  97. patsubst_expand (o, text, pattern, replace, pattern_percent, replace_percent)
  98.      char *o;
  99.      char *text;
  100.      register char *pattern, *replace;
  101.      register char *pattern_percent, *replace_percent;
  102. {
  103.   register int pattern_prepercent_len, pattern_postpercent_len;
  104.   register int replace_prepercent_len, replace_postpercent_len;
  105.   register char *t;
  106.   unsigned int len;
  107.   int doneany = 0;
  108.  
  109.   /* We call find_percent on REPLACE before checking PATTERN so that REPLACE
  110.      will be collapsed before we call subst_expand if PATTERN has no %.  */
  111.   if (replace_percent == 0)
  112.     replace_percent = find_percent (replace);
  113.   if (replace_percent != 0)
  114.     {
  115.       /* Record the length of REPLACE before and after the % so
  116.      we don't have to compute these lengths more than once.  */
  117.       replace_prepercent_len = replace_percent - replace;
  118.       replace_postpercent_len = strlen (replace_percent + 1);
  119.     }
  120.   else
  121.     /* We store the length of the replacement
  122.        so we only need to compute it once.  */
  123.     replace_prepercent_len = strlen (replace);
  124.  
  125.   if (pattern_percent == 0)
  126.     pattern_percent = find_percent (pattern);
  127.   if (pattern_percent == 0)
  128.     /* With no % in the pattern, this is just a simple substitution.  */
  129.     return subst_expand (o, text, pattern, replace,
  130.              strlen (pattern), strlen (replace), 1, 0);
  131.  
  132.   /* Record the length of PATTERN before and after the %
  133.      so we don't have to compute it more than once.  */
  134.   pattern_prepercent_len = pattern_percent - pattern;
  135.   pattern_postpercent_len = strlen (pattern_percent + 1);
  136.  
  137.   while (t = find_next_token (&text, &len))
  138.     {
  139.       int fail = 0;
  140.  
  141.       /* Is it big enough to match?  */
  142.       if (len < pattern_prepercent_len + pattern_postpercent_len)
  143.     fail = 1;
  144.  
  145.       /* Does the prefix match?  */
  146.       if (!fail && pattern_prepercent_len > 0
  147.       && (*t != *pattern
  148.           || t[pattern_prepercent_len - 1] != pattern_percent[-1]
  149.           || strncmp (t + 1, pattern + 1, pattern_prepercent_len - 1)))
  150.     fail = 1;
  151.  
  152.       /* Does the suffix match?  */
  153.       if (!fail && pattern_postpercent_len > 0
  154.       && (t[len - 1] != pattern_percent[pattern_postpercent_len]
  155.           || t[len - pattern_postpercent_len] != pattern_percent[1]
  156.           || strncmp (&t[len - pattern_postpercent_len],
  157.               &pattern_percent[1], pattern_postpercent_len - 1)))
  158.     fail = 1;
  159.  
  160.       if (fail)
  161.     /* It didn't match.  Output the string.  */
  162.     o = variable_buffer_output (o, t, len);
  163.       else
  164.     {
  165.       /* It matched.  Output the replacement.  */
  166.  
  167.       /* Output the part of the replacement before the %.  */
  168.       o = variable_buffer_output (o, replace, replace_prepercent_len);
  169.  
  170.       if (replace_percent != 0)
  171.         {
  172.           /* Output the part of the matched string that
  173.          matched the % in the pattern.  */
  174.           o = variable_buffer_output (o, t + pattern_prepercent_len,
  175.                       len - (pattern_prepercent_len
  176.                          + pattern_postpercent_len));
  177.           /* Output the part of the replacement after the %.  */
  178.           o = variable_buffer_output (o, replace_percent + 1,
  179.                       replace_postpercent_len);
  180.         }
  181.     }
  182.  
  183.       /* Output a space, but not if the replacement is "".  */
  184.       if (fail || replace_prepercent_len > 0
  185.       || (replace_percent != 0 && len + replace_postpercent_len > 0))
  186.     {
  187.       o = variable_buffer_output (o, " ", 1);
  188.       doneany = 1;
  189.     }
  190.     }
  191.   if (doneany)
  192.     /* Kill the last space.  */
  193.     --o;
  194.  
  195.   return o;
  196. }
  197.  
  198. /* Handle variable-expansion-time functions such as $(dir foo/bar) ==> foo/  */
  199.  
  200. /* These enumeration constants distinguish the
  201.    various expansion-time built-in functions.  */
  202.  
  203. enum function
  204.   {
  205.     function_subst,
  206.     function_addsuffix,
  207.     function_addprefix,
  208.     function_dir,
  209.     function_notdir,
  210.     function_suffix,
  211.     function_basename,
  212.     function_wildcard,
  213.     function_firstword,
  214.     function_word,
  215.     function_words,
  216.     function_findstring,
  217.     function_strip,
  218.     function_join,
  219.     function_patsubst,
  220.     function_filter,
  221.     function_filter_out,
  222.     function_foreach,
  223.     function_sort,
  224.     function_origin,
  225.     function_shell,
  226.     function_invalid
  227.   };
  228.  
  229. /* Greater than the length of any function name.  */
  230. #define MAXFUNCTIONLEN 11
  231.  
  232. /* The function names and lengths of names, for looking them up.  */
  233.  
  234. static struct
  235.   {
  236.     char *name;
  237.     unsigned int len;
  238.     enum function function;
  239.   } function_table[] =
  240.   {
  241.     { "subst", 5, function_subst },
  242.     { "addsuffix", 9, function_addsuffix },
  243.     { "addprefix", 9, function_addprefix },
  244.     { "dir", 3, function_dir },
  245.     { "notdir", 6, function_notdir },
  246.     { "suffix", 6, function_suffix },
  247.     { "basename", 8, function_basename },
  248.     { "wildcard", 8, function_wildcard },
  249.     { "firstword", 9, function_firstword },
  250.     { "word", 4, function_word },
  251.     { "words", 5, function_words },
  252.     { "findstring", 10, function_findstring },
  253.     { "strip", 5, function_strip },
  254.     { "join", 4, function_join },
  255.     { "patsubst", 8, function_patsubst },
  256.     { "filter",